<?php

namespace Xrfg\Api\Trading\Spot\Providers;

use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\ServiceProvider as IlluminateServiceProvider;
use Xrfg\Api\Trading\Spot\Console\Huobi;
use Xrfg\Api\Trading\Spot\Console\Kline;
use Xrfg\Api\Trading\Spot\Console\PairConfig;
use Xrfg\Api\Trading\Spot\Console\RebuildOrderBook;
use Xrfg\Api\Trading\Spot\Console\SupervisorConfig;
use Xrfg\Api\Trading\Spot\Events\Kline1SavedEvent;
use Xrfg\Api\Trading\Spot\Events\KlineSavedEvent;
use Xrfg\Api\Trading\Spot\Events\OrderCreatedEvent;
use Xrfg\Api\Trading\Spot\Events\OrderUpdatedEvent;
use Xrfg\Api\Trading\Spot\Events\TradeSavedEvent;
use Xrfg\Api\Trading\Spot\Listeners\DispatchMatchJob;
use Xrfg\Api\Trading\Spot\Listeners\SaveKline;
use Xrfg\Api\Trading\Spot\Listeners\SaveTicker;
use Xrfg\Api\Trading\Spot\Listeners\TakerRobot;
use Xrfg\Api\Trading\Spot\Listeners\UpdateOrderBook;
use Xrfg\Api\Trading\Spot\Listeners\UpdateTicker;
use Xrfg\Api\Trading\Spot\Listeners\UpdateTrade;

class ServiceProvider extends IlluminateServiceProvider
{
    public function boot()
    {
        $this->registerPublishing();
        $this->registerRoutes();
        $this->registerCommands();
        $this->registerEvents();
        $this->registerValidator();
    }

    public function register()
    {
        $this->mergeConfigFrom(
            __DIR__.'/../../config/error.php',
            'error'
        );
    }

    private function registerPublishing()
    {
        if ($this->app->runningInConsole()) {
            $this->publishes([
                __DIR__.'/../../config/huobi.php' => config_path('huobi.php'),
            ]);
        }
    }

    private function registerRoutes()
    {
        Route::prefix('api/spot')
            ->middleware('api')
            ->namespace('Xrfg\\Api\\Trading\\Spot\\Controllers')
            ->group(function () {
                $this->loadRoutesFrom(__DIR__.'/../../routes/api.php');
            });
    }

    private function registerCommands()
    {
        if ($this->app->runningInConsole()) {
            $this->commands([
                Kline::class,
                RebuildOrderBook::class,
                Huobi::class,
                SupervisorConfig::class,
                PairConfig::class,
            ]);
        }
    }

    private function registerEvents()
    {
        // 创建订单 -> 更新 orderbook
        Event::listen(OrderCreatedEvent::class, UpdateOrderBook::class);
        // 创建订单 -> 分发撮合任务到撮合队列
        Event::listen(OrderCreatedEvent::class, DispatchMatchJob::class);
        // 创建订单 -> 触发吃单机器人
        Event::listen(OrderCreatedEvent::class, TakerRobot::class);
        // 更新订单 -> 更新 orderbook
        Event::listen(OrderUpdatedEvent::class, UpdateOrderBook::class);
        // 成交订单 -> 更新 ticker
        Event::listen(TradeSavedEvent::class, UpdateTicker::class);
        // 成交订单 -> 更新 trades
        Event::listen(TradeSavedEvent::class, UpdateTrade::class);
        // 定时生成 1 分钟K线 -> 更新 ticker
        Event::listen(Kline1SavedEvent::class, SaveTicker::class);
        // K线数据变化 -> 更新 kline
        Event::listen(KlineSavedEvent::class, SaveKline::class);
    }

    private function registerValidator()
    {
        Validator::extend('price_decimals', '\Xrfg\Api\Trading\Spot\Rules\Validator@priceDecimals');
        Validator::extend('number_decimals', '\Xrfg\Api\Trading\Spot\Rules\Validator@numberDecimals');
    }
}
